﻿using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
using Newtonsoft.Json;
using System.Net.Http.Headers;
using System.Security.Authentication;
using System.Text;
using D.ATN.NLogsUtil;
using System.Threading;
using System;
using System.Net.Http;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Linq;

namespace D.ATN.HttpUtil
{
    public class HttpClientHelper
    {
        private static JsonSerializerSettings jsonSerializerSettings = new JsonSerializerSettings()
        {
            //NullValueHandling = NullValueHandling.Ignore,
            DateFormatHandling = Newtonsoft.Json.DateFormatHandling.MicrosoftDateFormat,
            //ContractResolver = new CamelCasePropertyNamesContractResolver() ,
        };

        private static void InitHttpClient(int timeOut, Dictionary<string, string> headers)
        {
            if (ServiceLocator.Client == null)
            {
                ServiceLocator.Client = new HttpClient(new HttpClientHandler()
                {
                    SslProtocols = SslProtocols.None,
                    ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => { return true; }
                });
                //client.BaseAddress = new Uri(HttpUrl.BASE_ADDRESS);
                ServiceLocator.Client.Timeout = TimeSpan.FromSeconds(timeOut);// 默认20秒
            }

            if (headers != null)
            {
                ServiceLocator.Client.DefaultRequestHeaders.Clear();
                foreach (var header in headers)
                {
                    if (ServiceLocator.Client.DefaultRequestHeaders.Where(m => m.Key == header.Key).Any())
                    {
                        ServiceLocator.Client.DefaultRequestHeaders.Remove(header.Key);
                    }
                    ServiceLocator.Client.DefaultRequestHeaders.Add(header.Key, header.Value);
                }
            }

        }


        public static async Task<ResponseRes<T>> HttpPostAsync<T>(string url, int timeOut, object body = null, string contentType = "application/json", Dictionary<string, string> headers = null)
        {
            try
            {
                InitHttpClient(timeOut, headers);
                var strBody = string.Empty;
                if (body != null)
                {
                    //jsonSerializerSettings.Converters.Add(new IsoDateTimeConverter { DateTimeFormat = "yyyy-MM-dd HH:mm:ss" });
                    strBody = JsonConvert.SerializeObject(body, Formatting.Indented, jsonSerializerSettings);
                }

                using (HttpContent httpContent = new StringContent(strBody, Encoding.UTF8))
                {
                    if (contentType != null)
                        httpContent.Headers.ContentType = new MediaTypeHeaderValue(contentType);

                    HttpResponseMessage response = await ServiceLocator.Client.PostAsync(url, httpContent);
                    if (response.IsSuccessStatusCode)
                    {
                        var res = await response.Content.ReadAsStringAsync();

                        if (res != null)
                        {
                            var responseRes = JsonConvert.DeserializeObject<ResponseRes<T>>(res, new JsonSerializerSettings()
                            {
                                NullValueHandling = NullValueHandling.Ignore
                            });
                            return responseRes;
                        }
                    }
                    else
                    {
                        throw new Exception($"响应状态为{response.StatusCode.ToString()}");
                    }
                }
            }
            catch (Exception ex)
            {
                NLogHelper.Error($"{url}HTTP Post：{ex.Message}");
                NLogHelper.Error($"{url}HTTP Post：{ex.StackTrace}");
                return new ResponseRes<T>()
                {
                    code = 300,
                    data = default(T),
                    message = "返回数据异常"
                };
            }
            return new ResponseRes<T>()
            {
                code = 300,
                data = default(T),
                message = "返回数据异常"
            };
        }

        public static async Task<ResponseRes<T>> HttpPostAsync<T>(string url, int timeOut, string body, string contentType = "application/json", Dictionary<string, string> headers = null)
        {
            try
            {
                InitHttpClient(timeOut, headers);

                using (HttpContent httpContent = new StringContent(body, Encoding.UTF8))
                {
                    if (contentType != null)
                        httpContent.Headers.ContentType = new MediaTypeHeaderValue(contentType);

                    HttpResponseMessage response = await ServiceLocator.Client.PostAsync(url, httpContent);
                    if (response.IsSuccessStatusCode)
                    {
                        var res = await response.Content.ReadAsStringAsync();
                        if (res != null)
                        {
                            var responseRes = JsonConvert.DeserializeObject<ResponseRes<T>>(res, new JsonSerializerSettings()
                            {
                                NullValueHandling = NullValueHandling.Ignore
                            });
                            return responseRes;
                        }
                    }
                    else
                    {
                        return new ResponseRes<T>()
                        {
                            code = 300,
                            data = default(T),
                            message = $"响应状态为{response.StatusCode}"
                        };
                    }
                }
            }
            catch (Exception ex)
            {
                NLogHelper.Error($"{url}HTTP Post：{ex.Message}");
                NLogHelper.Error($"{url}HTTP Post：{ex.StackTrace}");

                return new ResponseRes<T>()
                {
                    code = 300,
                    data = default(T),
                    message = "返回数据异常"
                };
            }
            return new ResponseRes<T>()
            {
                code = 300,
                data = default(T),
                message = "返回数据异常"
            };
        }


        public static string ObjectToGetParam(object obj)
        {
            StringBuilder strBui = new StringBuilder();
            if (obj != null)
            {
                System.Reflection.PropertyInfo[] proArray = obj.GetType().GetProperties();
                foreach (System.Reflection.PropertyInfo pro in proArray)
                {
                    if (strBui.Length < 1)
                    {
                        strBui.Append("?");
                    }
                    else
                    {
                        strBui.Append("&");
                    }
                    strBui.Append(string.Format("{0}={1}", pro.Name, pro.GetValue(obj, null)));
                }
            }
            return strBui.ToString();
        }

        public static async Task<T> HttpGetAsync<T>(string url, int timeOut, object body = null, Dictionary<string, string> headers = null)
        {
            try
            {
                InitHttpClient(timeOut, headers);

                if (body != null)
                {
                    url = url + ObjectToGetParam(body);
                }
                HttpResponseMessage response = await ServiceLocator.Client.GetAsync(url);
                var res = await response.Content.ReadAsStringAsync();
                if (res != null)
                {
                    var jsonObj = JsonConvert.DeserializeObject<T>(res);
                    if (jsonObj == null)
                    {
                        NLogHelper.Error($"{url}HTTP Get,序列化失败：{res}");
                    }
                    else
                    {
                        return jsonObj;
                    }
                }
            }
            catch (Exception ex)
            {
                NLogHelper.Error($"{url}HTTP Get：{ex.Message}");
                NLogHelper.Error($"{url}HTTP Get：{ex.StackTrace}");
            }
            return default(T);
        }

        public static async Task<string> HttpPostAsync(string url, string body = null, int timeOut = 120, string contentType = "application/json", Dictionary<string, string> headers = null)
        {
            try
            {
                InitHttpClient(timeOut, headers);
                //var strBody = string.Empty;
                //if (body != null)
                //{
                //    strBody = JsonConvert.SerializeObject(body, Formatting.Indented, jsonSerializerSettings);
                //}

                using (HttpContent httpContent = new StringContent(body, Encoding.UTF8))
                {
                    if (contentType != null)
                        httpContent.Headers.ContentType = new MediaTypeHeaderValue(contentType);

                    HttpResponseMessage response = await ServiceLocator.Client.PostAsync(url, httpContent);
                    if (response.IsSuccessStatusCode)
                    {
                        return await response.Content.ReadAsStringAsync();
                    }
                    else
                    {
                        throw new Exception($"响应状态为{response.StatusCode}");
                    }
                }
            }
            catch (Exception ex)
            {
                NLogHelper.Error($"{url}HTTP Post：{ex.Message}");
                NLogHelper.Error($"{url}HTTP Post：{ex.StackTrace}");
                return ex.Message;
            }
            return null;
        }

        public static async Task<string> HttpGetAsync(string url, object body = null, int timeOut = 120, Dictionary<string, string> headers = null)
        {
            try
            {
                InitHttpClient(timeOut, headers);
                if (body != null)
                {
                    url = url + ObjectToGetParam(body);
                }
                HttpResponseMessage response = await ServiceLocator.Client.GetAsync(url);
                return await response.Content.ReadAsStringAsync();
            }
            catch (Exception ex)
            {
                NLogHelper.Error($"{url}HTTP Get：{ex.Message}");
                NLogHelper.Error($"{url}HTTP Get：{ex.StackTrace}");
            }
            return null;
        }
    }
}
